import React, { Component } from 'react';
import PropTypes from 'prop-types';

class LifeCycle extends Component {

    static defaultProps = { // 这里可以设置props的默认值，即没接收到参数时的值
        msg: 'props -> msg'
    }
    static propTypes = {
        msg: PropTypes.string.isRequired // 校验规则可以链式拼接
    }
    constructor(props) {
        super(props)
        console.log('~~constructor')
        this.state = {
            counter: 0
        }
    }
    componentWillMount() {
        console.log('~~componentWillMount 将废弃')
    }
    componentDidMount() {
        console.log('~~componentDidMount')
    }
    // 一个更新前的快照周期函数，在render之后update之前调用，并且只在更新渲染后调用
    // 可以在组件发生更改之前从DOM中获取一些信息，如滚动位置。返回的值会作为参数传给componentDidUpdate
    getSnapshotBeforeUpdate(preProps, preState) {
        console.log('~~新增：getSnapshotBeforeUpdate')
        return {
            msg: '来自getSnapshotBeforeUpdate的返回值'
        }
    }
    shouldComponentUpdate() {
        console.log('%c~~----shouldComponentUpdate  将废弃', 'background:skyblue')
        return this.state.counter !== 3
    }
    componentWillUpdate() {
        console.log('~~componentWillUpdate  将废弃')
    }
    componentDidUpdate(props,state,snapshot) {
        console.log('~~componentDidUpdate', {props,state,snapshot})
    }

    // 会在渲染前调用，并且初始化和更新的时候都会调用。次函数返回一个对象用于更新state，返回null则什么都不更新，但不阻止渲染。
    // 此生命周期和componentWillMount、componentWillUpdate、componentWillReceiveProps功能上冲突，同用会报警告
    // 注意函数前要写上 static
    static getDerivedStateFromProps(props, state) {
        // getDerivedStateFromProps
        console.log('~~新增：getDeriverdStateFromPros周期函数')
        return state.counter > 6 ? { counter: 0 } : null
    }

    setCounter = () => {
        this.setState({
            counter: this.state.counter + 1
        })
    }
    render() {
        const { counter } = this.state
        console.log(' ~~ render', this.props, this.state)
        return (
            <div>
                <h3>生命周期</h3>
                <div>其中componentWillMount、shouldComponentUpdate、componentWillUpdate这三个生命周期函数将被废弃，原因是react引入的fiber模型与之不兼容</div>
                <div>为消除警告，可以给这几个生命周期手动添加“UNSAFE_”前缀，注意严格模式是不需要添加前缀的</div>
                <div>如果要添加的地方太多，可以用命令 <code>npx react-codemod rename-unsafe-lifecycles &lt;path&gt; </code></div>
                <div>this.props.msg: {this.props.msg}</div>
                <div>this.state.counter: {counter}</div>
                <button onClick={this.setCounter}>增加计数</button>
                {counter % 3 > 0 && <h4><Child count={counter} /></h4>}
            </div>
        );
    }
}

class Child extends Component {
    componentWillReceiveProps() {
        console.log('~~child——componentWillReceiveProps 子组件将接收参数，初次渲染时不会执行')
    }
    componentWillUnmount() {
        console.log('~~child——componentWillUnmount 子组件将被卸载')
    }
    render() {
        return <div>
            child——this.props.count:{this.props.count}
            <p>对3求余显示</p>
        </div>
    }
}
export default LifeCycle;
